/**
 * 动画控制器类
 * 管理游戏中的CSS动画效果和过渡
 */

/**
 * 动画类型枚举
 */
export enum AnimationType {
  // 角色动画
  CHARACTER_RUNNING = 'character-running',
  CHARACTER_JUMPING = 'character-jumping',
  CHARACTER_SLIDING = 'character-sliding',
  CHARACTER_HURT = 'character-hurt',
  CHARACTER_DEATH = 'character-death',
  CHARACTER_VICTORY = 'character-victory',

  // UI过渡动画
  FADE_IN = 'fade-in',
  FADE_OUT = 'fade-out',
  SLIDE_IN_TOP = 'slide-in-top',
  SLIDE_IN_BOTTOM = 'slide-in-bottom',
  SLIDE_IN_LEFT = 'slide-in-left',
  SLIDE_IN_RIGHT = 'slide-in-right',
  SCALE_IN = 'scale-in',
  SCALE_OUT = 'scale-out',
  BOUNCE_IN = 'bounce-in',
  ROTATE_IN = 'rotate-in',

  // 游戏特效动画
  SCORE_FLY = 'score-fly',
  POWERUP_COLLECT = 'powerup-collect',
  EXPLOSION = 'explosion',
  BLINK = 'blink',
  GLOW = 'glow',
  RAINBOW = 'rainbow'
}

/**
 * 动画配置接口
 */
export interface AnimationConfig {
  /** 动画类型 */
  type: AnimationType
  /** 动画持续时间（毫秒） */
  duration?: number
  /** 动画延迟（毫秒） */
  delay?: number
  /** 动画缓动函数 */
  easing?: string
  /** 动画迭代次数 */
  iterations?: number | 'infinite'
  /** 动画填充模式 */
  fillMode?: 'none' | 'forwards' | 'backwards' | 'both'
  /** 动画完成回调 */
  onComplete?: () => void
  /** 动画开始回调 */
  onStart?: () => void
}

/**
 * 动画状态接口
 */
export interface AnimationState {
  /** 动画ID */
  id: string
  /** 目标元素 */
  element: HTMLElement
  /** 动画配置 */
  config: AnimationConfig
  /** 动画开始时间 */
  startTime: number
  /** 是否正在播放 */
  isPlaying: boolean
  /** 动画实例 */
  animation?: Animation
}

/**
 * 动画控制器类
 * 提供统一的动画管理和控制功能
 */
export class AnimationController {
  private activeAnimations: Map<string, AnimationState> = new Map()
  private animationIdCounter = 0
  private isEnabled = true

  /**
   * 创建动画控制器实例
   */
  constructor() {
    this.checkReducedMotionPreference()
  }

  /**
   * 检查用户的减少动画偏好设置
   */
  private checkReducedMotionPreference(): void {
    if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
      this.isEnabled = false
      console.log('动画已禁用：用户偏好减少动画')
    }
  }

  /**
   * 启用或禁用动画
   * @param enabled - 是否启用动画
   */
  public setEnabled(enabled: boolean): void {
    this.isEnabled = enabled
    
    if (!enabled) {
      // 停止所有正在播放的动画
      this.stopAllAnimations()
    }
  }

  /**
   * 播放动画
   * @param element - 目标元素
   * @param config - 动画配置
   * @returns 动画ID
   */
  public playAnimation(element: HTMLElement, config: AnimationConfig): string {
    if (!this.isEnabled) {
      // 如果动画被禁用，直接调用完成回调
      if (config.onComplete) {
        setTimeout(config.onComplete, 0)
      }
      return ''
    }

    const animationId = this.generateAnimationId()
    
    // 创建动画状态
    const animationState: AnimationState = {
      id: animationId,
      element,
      config,
      startTime: Date.now(),
      isPlaying: false
    }

    // 应用CSS类动画
    this.applyCSSAnimation(animationState)
    
    // 存储动画状态
    this.activeAnimations.set(animationId, animationState)

    return animationId
  }

  /**
   * 应用CSS类动画
   * @param animationState - 动画状态
   */
  private applyCSSAnimation(animationState: AnimationState): void {
    const { element, config } = animationState
    const { type, duration, delay, easing, iterations, fillMode } = config

    // 检查元素是否有效
    if (!element || !element.classList) return

    // 移除之前的动画类
    this.removeAnimationClasses(element)

    // 添加动画类
    const animationClasses = this.getAnimationClasses(type)
    animationClasses.forEach(className => {
      element.classList.add(className)
    })

    // 设置动画样式
    if (duration) {
      element.style.animationDuration = `${duration}ms`
    }
    if (delay) {
      element.style.animationDelay = `${delay}ms`
    }
    if (easing) {
      element.style.animationTimingFunction = easing
    }
    if (iterations) {
      element.style.animationIterationCount = iterations.toString()
    }
    if (fillMode) {
      element.style.animationFillMode = fillMode
    }

    animationState.isPlaying = true

    // 调用开始回调
    if (config.onStart) {
      config.onStart()
    }

    // 监听动画结束事件
    const handleAnimationEnd = () => {
      this.onAnimationComplete(animationState.id)
      element.removeEventListener('animationend', handleAnimationEnd)
    }

    element.addEventListener('animationend', handleAnimationEnd)
  }

  /**
   * 获取动画CSS类名
   * @param type - 动画类型
   * @returns CSS类名数组
   */
  private getAnimationClasses(type: AnimationType): string[] {
    const classMap: Record<AnimationType, string[]> = {
      [AnimationType.CHARACTER_RUNNING]: ['character-animation', 'running'],
      [AnimationType.CHARACTER_JUMPING]: ['character-animation', 'jumping'],
      [AnimationType.CHARACTER_SLIDING]: ['character-animation', 'sliding'],
      [AnimationType.CHARACTER_HURT]: ['character-animation', 'hurt'],
      [AnimationType.CHARACTER_DEATH]: ['character-animation', 'death'],
      [AnimationType.CHARACTER_VICTORY]: ['character-animation', 'victory'],
      
      [AnimationType.FADE_IN]: ['ui-transition', 'fade-in'],
      [AnimationType.FADE_OUT]: ['ui-transition', 'fade-out'],
      [AnimationType.SLIDE_IN_TOP]: ['ui-transition', 'slide-in-top'],
      [AnimationType.SLIDE_IN_BOTTOM]: ['ui-transition', 'slide-in-bottom'],
      [AnimationType.SLIDE_IN_LEFT]: ['ui-transition', 'slide-in-left'],
      [AnimationType.SLIDE_IN_RIGHT]: ['ui-transition', 'slide-in-right'],
      [AnimationType.SCALE_IN]: ['ui-transition', 'scale-in'],
      [AnimationType.SCALE_OUT]: ['ui-transition', 'scale-out'],
      [AnimationType.BOUNCE_IN]: ['ui-transition', 'bounce-in'],
      [AnimationType.ROTATE_IN]: ['ui-transition', 'rotate-in'],
      
      [AnimationType.SCORE_FLY]: ['game-effect', 'score-fly'],
      [AnimationType.POWERUP_COLLECT]: ['game-effect', 'powerup-collect'],
      [AnimationType.EXPLOSION]: ['game-effect', 'explosion'],
      [AnimationType.BLINK]: ['game-effect', 'blink'],
      [AnimationType.GLOW]: ['game-effect', 'glow'],
      [AnimationType.RAINBOW]: ['game-effect', 'rainbow']
    }

    return classMap[type] || []
  }

  /**
   * 移除元素上的动画类
   * @param element - 目标元素
   */
  private removeAnimationClasses(element: HTMLElement): void {
    if (!element || !element.classList) return

    const animationClasses = [
      'character-animation', 'running', 'jumping', 'sliding', 'hurt', 'death', 'victory',
      'ui-transition', 'fade-in', 'fade-out', 'slide-in-top', 'slide-in-bottom',
      'slide-in-left', 'slide-in-right', 'scale-in', 'scale-out', 'bounce-in', 'rotate-in',
      'game-effect', 'score-fly', 'powerup-collect', 'explosion', 'blink', 'glow', 'rainbow'
    ]

    animationClasses.forEach(className => {
      if (element.classList.contains(className)) {
        element.classList.remove(className)
      }
    })

    // 清除内联动画样式
    if (element.style) {
      element.style.animationDuration = ''
      element.style.animationDelay = ''
      element.style.animationTimingFunction = ''
      element.style.animationIterationCount = ''
      element.style.animationFillMode = ''
    }
  }

  /**
   * 停止动画
   * @param animationId - 动画ID
   */
  public stopAnimation(animationId: string): void {
    const animationState = this.activeAnimations.get(animationId)
    if (!animationState) return

    const { element } = animationState

    // 移除动画类
    this.removeAnimationClasses(element)

    // 标记为停止
    animationState.isPlaying = false

    // 从活动动画中移除
    this.activeAnimations.delete(animationId)
  }

  /**
   * 停止元素上的所有动画
   * @param element - 目标元素
   */
  public stopElementAnimations(element: HTMLElement): void {
    const animationsToStop: string[] = []

    this.activeAnimations.forEach((animationState, id) => {
      if (animationState.element === element) {
        animationsToStop.push(id)
      }
    })

    animationsToStop.forEach(id => this.stopAnimation(id))
  }

  /**
   * 停止所有动画
   */
  public stopAllAnimations(): void {
    const animationIds = Array.from(this.activeAnimations.keys())
    animationIds.forEach(id => this.stopAnimation(id))
  }

  /**
   * 动画完成处理
   * @param animationId - 动画ID
   */
  private onAnimationComplete(animationId: string): void {
    const animationState = this.activeAnimations.get(animationId)
    if (!animationState) return

    const { element, config } = animationState

    // 移除动画类（除非是无限循环动画）
    if (config.iterations !== 'infinite') {
      this.removeAnimationClasses(element)
    }

    // 调用完成回调
    if (config.onComplete) {
      config.onComplete()
    }

    // 从活动动画中移除
    this.activeAnimations.delete(animationId)
  }

  /**
   * 生成动画ID
   * @returns 唯一的动画ID
   */
  private generateAnimationId(): string {
    return `animation_${++this.animationIdCounter}_${Date.now()}`
  }

  /**
   * 获取活动动画数量
   * @returns 活动动画数量
   */
  public getActiveAnimationCount(): number {
    return this.activeAnimations.size
  }

  /**
   * 检查元素是否有活动动画
   * @param element - 目标元素
   * @returns 是否有活动动画
   */
  public hasActiveAnimations(element: HTMLElement): boolean {
    for (const animationState of this.activeAnimations.values()) {
      if (animationState.element === element && animationState.isPlaying) {
        return true
      }
    }
    return false
  }

  /**
   * 暂停所有动画
   */
  public pauseAllAnimations(): void {
    this.activeAnimations.forEach(animationState => {
      if (animationState.isPlaying) {
        animationState.element.style.animationPlayState = 'paused'
      }
    })
  }

  /**
   * 恢复所有动画
   */
  public resumeAllAnimations(): void {
    this.activeAnimations.forEach(animationState => {
      if (animationState.isPlaying) {
        animationState.element.style.animationPlayState = 'running'
      }
    })
  }

  /**
   * 清理资源
   */
  public dispose(): void {
    this.stopAllAnimations()
    this.activeAnimations.clear()
  }
}

/**
 * 全局动画控制器实例
 */
export const animationController = new AnimationController()

/**
 * 动画工具函数
 */
export class AnimationUtils {
  /**
   * 为元素添加硬件加速
   * @param element - 目标元素
   */
  static enableHardwareAcceleration(element: HTMLElement): void {
    element.classList.add('hardware-accelerated')
  }

  /**
   * 为元素添加动画性能优化
   * @param element - 目标元素
   */
  static optimizeForAnimation(element: HTMLElement): void {
    element.classList.add('optimized-animation')
  }

  /**
   * 创建动画序列
   * @param animations - 动画配置数组
   * @param element - 目标元素
   * @returns Promise，在所有动画完成后resolve
   */
  static async playAnimationSequence(
    animations: AnimationConfig[],
    element: HTMLElement
  ): Promise<void> {
    for (const config of animations) {
      await new Promise<void>((resolve) => {
        const configWithCallback: AnimationConfig = {
          ...config,
          onComplete: () => {
            if (config.onComplete) {
              config.onComplete()
            }
            resolve()
          }
        }
        animationController.playAnimation(element, configWithCallback)
      })
    }
  }

  /**
   * 创建并行动画
   * @param animations - 动画配置数组
   * @param elements - 目标元素数组
   * @returns Promise，在所有动画完成后resolve
   */
  static async playParallelAnimations(
    animations: AnimationConfig[],
    elements: HTMLElement[]
  ): Promise<void> {
    const promises = animations.map((config, index) => {
      const element = elements[index]
      if (!element) return Promise.resolve()

      return new Promise<void>((resolve) => {
        const configWithCallback: AnimationConfig = {
          ...config,
          onComplete: () => {
            if (config.onComplete) {
              config.onComplete()
            }
            resolve()
          }
        }
        animationController.playAnimation(element, configWithCallback)
      })
    })

    await Promise.all(promises)
  }

  /**
   * 检查浏览器是否支持CSS动画
   * @returns 是否支持CSS动画
   */
  static supportsCSSAnimations(): boolean {
    const element = document.createElement('div')
    return 'animationName' in element.style ||
           'webkitAnimationName' in element.style ||
           'mozAnimationName' in element.style
  }

  /**
   * 获取动画持续时间
   * @param element - 目标元素
   * @returns 动画持续时间（毫秒）
   */
  static getAnimationDuration(element: HTMLElement): number {
    const computedStyle = window.getComputedStyle(element)
    const duration = computedStyle.animationDuration
    
    if (duration === 'auto' || !duration) return 0
    
    // 解析时间值（支持s和ms）
    const match = duration.match(/^([\d.]+)(s|ms)$/)
    if (!match) return 0
    
    const value = parseFloat(match[1])
    const unit = match[2]
    
    return unit === 's' ? value * 1000 : value
  }
}